﻿using Common.Tool;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace Common.View.Base
{
    public abstract class BindableBase : LogBase,INotifyPropertyChanged
    {
        //
        // 摘要:
        //     在属性值更改时发生。
        public event PropertyChangedEventHandler PropertyChanged;

        //
        // 摘要:
        //     检查属性是否已经与所需的值匹配。 设置属性并仅在必要时通知侦听器。
        //
        // 参数:
        //   storage:
        //     设置的属性，需要有get;set;
        //
        //   value:
        //     设置的值
        //
        //   propertyName:
        //     用于通知侦听器的属性的名称。 该值是可选的，可以在从支持CallerMemberName的编译器中调用时自动提供。
        //
        // 类型参数:
        //   T:
        //     属性的类型
        //
        // 返回结果:
        //     如果值被更改，则为True，如果现有值与期望值匹配，则为false。
        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(storage, value))
            {
                return false;
            }

            storage = value;
            RaisePropertyChanged(propertyName);
            return true;
        }

        //
        // 摘要:
        //     检查属性是否已经与所需的值匹配。 设置属性并仅在必要时通知侦听器。
        //
        // 参数:
        //   storage:
        //     设置的属性，需要有get;set;
        //
        //   value:
        //     设置的值
        //
        //   onChanged:
        //     更改属性值后调用的操作。
        //
        //   propertyName:
        //     用于通知侦听器的属性的名称。 该值是可选的，可以在从支持CallerMemberName的编译器中调用时自动提供。
        //
        // 类型参数:
        //   T:
        //     属性的类型
        //
        // 返回结果:
        //     如果值被更改，则为True，如果现有值与期望值匹配，则为false。
        protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(storage, value))
            {
                return false;
            }

            storage = value;
            onChanged?.Invoke();
            RaisePropertyChanged(propertyName);
            return true;
        }

        //
        // 摘要:
        //     引发此对象的PropertyChanged事件。
        //
        // 参数:
        //   propertyName:
        //     用于通知侦听器的属性的名称。 该值是可选的，可以在从支持System.Runtime.CompilerServices.CallerMemberNameAttribute的编译器中调用时自动提供。
        public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        //
        // 摘要:
        //     引发此对象的PropertyChanged事件。
        //
        // 参数:
        //   propertyName:
        //     用于通知侦听器的属性的名称。
        protected virtual void OnPropertyChanged(string propertyName)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        //
        // 摘要:
        //     引发此对象的PropertyChanged事件。
        //
        // 参数:
        //   args:
        //     这是 PropertyChangedEventArgs
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
        {
            this.PropertyChanged?.Invoke(this, args);
        }
    }
}
